/**************************************************************************************
 *
 * @(#) EzvizService.java
 * @Package com.jgdt.jgdtkasannong_university_gene_backend.service.base.video
 **************************************************************************************/
package com.jgdt.jgdtkasannong_university_gene_backend.service.base.video.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jgdt.jgdtkasannong_university_gene_backend.common.Sysconstant;
import com.jgdt.jgdtkasannong_university_gene_backend.config.enums.FilePatternsEnums;
import com.jgdt.jgdtkasannong_university_gene_backend.config.enums.SysValueSetEnums;
import com.jgdt.jgdtkasannong_university_gene_backend.config.enums.video.ys.ApiResultCodeEnums;
import com.jgdt.jgdtkasannong_university_gene_backend.dto.GetDeviceChannelsResult;
import com.jgdt.jgdtkasannong_university_gene_backend.dto.ReDeviceChannelsVo;
import com.jgdt.jgdtkasannong_university_gene_backend.dto.ReDeviceChannelsVoResult;
import com.jgdt.jgdtkasannong_university_gene_backend.service.base.video.FireflyCloudEzvizService;
import com.jgdt.jgdtkasannong_university_gene_backend.service.content.MediaService;
import com.jgdt.jgdtkasannong_university_gene_backend.utils.IdUtil;
import com.jgdt.jgdtkasannong_university_gene_backend.vo.base.vido.GetVidoVo;
import com.jgdt.jgdtkasannong_university_gene_backend.vo.base.vido.ys.DeviceChannelsVo;
import lombok.extern.slf4j.Slf4j;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @description: 萤石云服务实现
 * @author: huangAn
 * @createDate: 2025/05/09
 */
@Service
@Slf4j
public class FireflyCloudEzvizServiceImpl implements FireflyCloudEzvizService {


    /**
     * 萤石云接口请求前缀（域名） todo 地址可更改为配置项
     */
    private static final String YSY_API_DOMAIN_NAME ="https://open.ys7.com";

    /**
     * 获取token
     */
    private static final String TOKEN_GET_URL =YSY_API_DOMAIN_NAME+"/api/lapp/token/get";
    /**
     * 获取设备序列视频rul
     */
    private static final String LIVE_ADDRESS_URL =YSY_API_DOMAIN_NAME+"/api/lapp/v2/live/address/get";
    /**
     *
     * 获取设备下所有通道信息
     */
    private static final String CAMERA_LIST_URL =YSY_API_DOMAIN_NAME+"/api/lapp/device/camera/list";

    /**
     * 视频图片抓取 url
     */
    private static final String CAPTURE_SAVE_URL=YSY_API_DOMAIN_NAME+"/api/open/cloud/v1/capture/save";


    private final OkHttpClient httpClient = new OkHttpClient();
    private final ObjectMapper objectMapper = new ObjectMapper();

    private String accessToken;
    private long tokenExpireTime;
    @Autowired
    private MediaService mediaService;

    /**************************************** 萤石云 方法  ****************************************/
    /**
     * 获取AccessToken
     */
    private String getAccessToken(String appKey, String appSecret) {
        if (accessToken != null && System.currentTimeMillis() < tokenExpireTime) {
            return accessToken;
        }
        FormBody.Builder formBuilder = new FormBody.Builder().add("appKey", appKey).add("appSecret", appSecret);
        Request request = new Request.Builder().url(TOKEN_GET_URL).post(formBuilder.build()).build();
        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            String responseBody = response.body().string();
            Map<String, Object> result = objectMapper.readValue(responseBody, Map.class);
            if (ApiResultCodeEnums.SUCCESS.getCode().equals(result.get("code"))) {
                Map<String, Object> data = (Map<String, Object>) result.get("data");
                accessToken = (String) data.get("accessToken");
                Long expireTime = (Long) data.get("expireTime");
                int expireTimeInt = expireTime.intValue();
                tokenExpireTime = System.currentTimeMillis() + (expireTimeInt - 300) * 1000L;
//                tokenExpireTime = System.currentTimeMillis() + ((Integer) data.get("expireTime") - 300) * 1000L;
                return accessToken;
            } else {
                log.error("获取获取萤石云,获取AccessToken getAccessToken err:" +result.get("msg"));
            }
        }catch (Exception e){
            log.error("获取获取萤石云,获取AccessToken getAccessToken err:" +e.getMessage());
            return null;
        }
        return null;
    }

    /**
     * 获取播放地址和实时视频截屏
     *
     * @param channelNo
     * @param deviceSerial
     * @return
     */
    private GetVidoVo getLiveAddressSnapshot(String token, Integer channelNo, String deviceSerial) throws FFmpegFrameGrabber.Exception {
        GetVidoVo getVidoVo = new GetVidoVo();
        if (channelNo == null || StringUtils.isEmpty(deviceSerial)) {
            return getVidoVo;
        }
        getVidoVo.setAccessToken(token);
        //1)获取视频播放地址
        try {
            //具体参数请参考 萤石云API文档：https://open.ys7.com/help/1414
            FormBody.Builder formBuilder = new FormBody.Builder()
                    .add("accessToken", token)
                    .add("deviceSerial", deviceSerial)
                    .add("channelNo", channelNo.toString()) // 默认通道1
                    .add("quality", "1")// 1-高清 视频清晰度，1-高清（主码流）、2-流畅（子码流）
////                .add("expireTime","")// 过期时长，单位秒；针对hls/rtmp/flv设置有效期，相对时间；30秒-720天
////                .add("type","3")//地址的类型，1-预览，2-本地录像回放，3-云存储录像回放，非必选，默认为1；回放仅支持rtmp、ezopen、flv协议
////                .add("startTime","")//本地录像/云存储录像回放开始时间,云存储开始结束时间必须在同一天，示例：2019-12-01 00:00:00
////                .add("stopTime","")//本地录像/云存储录像回放结束时间,云存储开始结束时间必须在同一天，示例：2019-12-01 23:59:59
////                .add("supportH265","")//请判断播放端是否要求播放视频为H265编码格式,1表示需要，0表示不要求
////                .add("playbackSpeed","")//回放倍速。倍速为 -1（ 支持的最大倍速）、0.5、1、2、4、8、16；仅支持protocol为4-flv且type为2-本地录像回放（ 部分设备可能不支持16倍速） 或者 3-云存储录像回放
////                .add("gbchannel","")//国标设备的通道编号，视频通道编号ID
                    ;
            Request request = new Request.Builder()
                    .url(LIVE_ADDRESS_URL)
                    .post(formBuilder.build())
                    .build();
            try (Response response = httpClient.newCall(request).execute()) {
                if (!response.isSuccessful()) {
                    throw new IOException("Unexpected code " + response);
                }
                String responseBody = response.body().string();
                Map<String, Object> result = objectMapper.readValue(responseBody, Map.class);
                if (ApiResultCodeEnums.SUCCESS.getCode().equals(result.get("code"))) {
                    Map<String, Object> data = (Map<String, Object>) result.get("data");
                    getVidoVo.setLiveAddress((String) data.get("url"));
                    getVidoVo.setLiveAddressTk(data.get("url") + "?accessToken=" + token);
                } else {
                    throw new IOException("Failed to get live address,err:" + result.get("msg"));
                }
            }
        } catch (Exception e) {
            log.error("获取获取萤石云,播放地址和实时视频截屏 getLiveAddressSnapshot,err:" + e.getMessage());
            e.printStackTrace();
        }

        //2）获取对应的播放截屏
        if (StringUtils.isEmpty(getVidoVo.getLiveAddressTk())) {
            return getVidoVo;
        }
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(getVidoVo.getLiveAddressTk());
        try {
            grabber.setFormat("flv");
            grabber.setOption("rtsp_transport", "tcp"); // 使用TCP传输
            grabber.start();
            Frame frame = grabber.grabImage();
            Java2DFrameConverter converter = new Java2DFrameConverter();
            BufferedImage bufferedImage = converter.convert(frame);

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "jpg", baos);
            getVidoVo.setSnapshot(String.valueOf(baos.toByteArray()));

        } catch (Exception e) {
            log.error("获取获取萤石云,getLiveAddressSnapshot,获取视频实时图片err:" + e.getMessage());
        } finally {
            grabber.stop();
        }
        return getVidoVo;
    }


    /**
     * 获取播放地址和实时视频截屏
     *
     * @param channelNo
     * @param deviceSerial
     * @return
     */
    private GetVidoVo getLiveAddressVideoImg(String token, Integer channelNo, String deviceSerial,String projectId, String fileId){
        GetVidoVo getVidoVo = new GetVidoVo();
        String ipPort=mediaService.getImgUrlHttp();
//        String slipIndex=null;
        String code = mediaService.getFilePatternsCode();
//        if (FilePatternsEnums.WIDOS.getCode().equals(code)) {
//            slipIndex = FilePatternsEnums.getEnumsByCode(FilePatternsEnums.WIDOS.getCode()).getSlipIndex();
//        } else if (FilePatternsEnums.LINX.getCode().equals(code)) {
//            slipIndex = FilePatternsEnums.getEnumsByCode(FilePatternsEnums.LINX.getCode()).getSlipIndex();
//        } else {
//            log.warn("getAfterLastSlash warn:配置文件FilePatternsEnums.java有问题");
//        }
        if (channelNo == null || StringUtils.isEmpty(deviceSerial)) {
            return getVidoVo;
        }
        getVidoVo.setAccessToken(token);
        //1)获取视频播放地址
        try {
            //具体参数请参考 萤石云API文档：https://open.ys7.com/help/1414
            FormBody.Builder formBuilder = new FormBody.Builder()
                    .add("accessToken", token)
                    .add("deviceSerial", deviceSerial)
                    .add("channelNo", channelNo.toString()) // 默认通道1
                    .add("quality", "1")// 1-高清 视频清晰度，1-高清（主码流）、2-流畅（子码流）
////                .add("expireTime","")// 过期时长，单位秒；针对hls/rtmp/flv设置有效期，相对时间；30秒-720天
////                .add("type","3")//地址的类型，1-预览，2-本地录像回放，3-云存储录像回放，非必选，默认为1；回放仅支持rtmp、ezopen、flv协议
////                .add("startTime","")//本地录像/云存储录像回放开始时间,云存储开始结束时间必须在同一天，示例：2019-12-01 00:00:00
////                .add("stopTime","")//本地录像/云存储录像回放结束时间,云存储开始结束时间必须在同一天，示例：2019-12-01 23:59:59
////                .add("supportH265","")//请判断播放端是否要求播放视频为H265编码格式,1表示需要，0表示不要求
////                .add("playbackSpeed","")//回放倍速。倍速为 -1（ 支持的最大倍速）、0.5、1、2、4、8、16；仅支持protocol为4-flv且type为2-本地录像回放（ 部分设备可能不支持16倍速） 或者 3-云存储录像回放
////                .add("gbchannel","")//国标设备的通道编号，视频通道编号ID
                    ;
            Request request = new Request.Builder()
                    .url(LIVE_ADDRESS_URL)
                    .post(formBuilder.build())
                    .build();
            try (Response response = httpClient.newCall(request).execute()) {
                if (!response.isSuccessful()) {
                    throw new IOException("Unexpected code " + response);
                }
                String responseBody = response.body().string();
                Map<String, Object> result = objectMapper.readValue(responseBody, Map.class);
                if (ApiResultCodeEnums.SUCCESS.getCode().equals(result.get("code"))) {
                    Map<String, Object> data = (Map<String, Object>) result.get("data");
                    getVidoVo.setLiveAddress((String) data.get("url"));
                    getVidoVo.setLiveAddressTk(data.get("url") + "?accessToken=" + token);
                    log.info("getLiveAddressVideoImg deviceSerial:"+deviceSerial+" data:"+data+",LiveAddress"+getVidoVo.getLiveAddress());
                } else {
                    log.warn("getLiveAddressVideoImg deviceSerial:"+deviceSerial+"获取视频播放地址异常err:"+result.get("msg"));
                    return getVidoVo;
                }
            }
        } catch (Exception e) {
            log.error("获取获取萤石云,播放地址和实时视频截屏 getLiveAddressVideoImg,err:" + e.getMessage());
            e.printStackTrace();
        }
        try {
            //2）获取对应的播放截屏
           String snapshot= this.getVideoImgTkChannels(token,deviceSerial,String.valueOf(channelNo),projectId,fileId);
           if(StringUtils.isNotEmpty(snapshot)){
               getVidoVo.setSnapshot(snapshot);
           }else {
               log.warn("getLiveAddressVideoImg this.getVideoImgTkChannels warn:获取图片地址 snapshot 为空...");
           }
        }catch (Exception e){
            log.error("getLiveAddressVideoImg this.getVideoImgTkChannels err:"+e.getMessage());
        }
        //设置默认 截屏图片
        String imgName=Sysconstant.VIDEO_IMG_IMPORTURL_NAME+ IdUtil.generateMathRandom(20)+".png";
        String imgUrl=null;
        if(FilePatternsEnums.WIDOS.getCode().equals(code)){
              imgUrl=Sysconstant.HTTP_INDEX +ipPort+"/"+ SysValueSetEnums.FRONT_VISIT_IMG_PREFIX.getValue()+"/"+imgName;
        }else if(FilePatternsEnums.LINX.getCode().equals(code)){
              imgUrl=Sysconstant.HTTP_INDEX +ipPort+"/"+ SysValueSetEnums.FRONT_VISIT_IMG_PREFIX.getValue()+Sysconstant.VIDEO_IMG_IMPORTURL+"/"+imgName;
        }else{
            log.warn("getLiveAddressVideoImg warn:FilePatternsEnums.WIDOS.getCode()...");
        }
        getVidoVo.setSnapImg(imgUrl);
        return getVidoVo;
    }

    /**
     * 获取萤石云通道信息
     * @param deviceSerial
     * @return
     * @throws IOException
     */
    private GetDeviceChannelsResult getDeviceChannels(String deviceSerial, String appKey, String appSecret) throws Exception {
        log.debug("getDeviceChannels-deviceSerial:"+deviceSerial+"appKey:"+appKey+",appSecret:"+appSecret);
        //获取tocken
        String accessToken = this.getAccessToken(appKey,appSecret);
        //具体参数请参考 萤石云API文档：https://open.ys7.com/help/1414
        FormBody.Builder formBuilder = new FormBody.Builder()
                .add("accessToken", accessToken)
                .add("deviceSerial", deviceSerial)
//                .add("pageStart", String.valueOf(pageNo - 1)) //分页 实际不支持,可与云平台沟通
//                .add("pageSize", String.valueOf(pageSize))
                ;
        Request request = new Request.Builder()
                .url(CAMERA_LIST_URL)
                .post(formBuilder.build())
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();
        GetDeviceChannelsResult getDeviceChannelsResult=new GetDeviceChannelsResult();
        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            String responseBody = response.body().string();

            Map<String, Object> result = objectMapper.readValue(responseBody, Map.class);
            log.info("getDeviceChannels-deviceSerial"+deviceSerial+",result:"+result);
            if (ApiResultCodeEnums.SUCCESS.getCode().equals(result.get("code"))) {
                //数据转换
                List<DeviceChannelsVo> reDataList = new ArrayList<>();
                ObjectMapper mapper = new ObjectMapper();
                if(ObjectUtils.isEmpty(result.get("data"))){
                    getDeviceChannelsResult.setDeviceChannelsVoList(new ArrayList<>());
                    return getDeviceChannelsResult;
                }
                for (Object item : (List<?>) result.get("data")) {
                    DeviceChannelsVo vo = mapper.convertValue(item, DeviceChannelsVo.class);
                    reDataList.add(vo);
                }
                getDeviceChannelsResult.setDeviceChannelsVoList(reDataList);
                log.info("getDeviceChannels-deviceSerial"+deviceSerial+"reDataList:"+reDataList);
                return  getDeviceChannelsResult;
            } else {
                getDeviceChannelsResult.setGetErrBool(true);
                getDeviceChannelsResult.setDeviceChannelsVoList(new ArrayList<>());
                log.error("getDeviceChannels-deviceSerial"+deviceSerial+"获取萤石云通道信息,getDeviceChannels err:"+result.get("msg"));
                return getDeviceChannelsResult;
            }
        }catch (Exception e){
            getDeviceChannelsResult.setGetErrBool(true);
            getDeviceChannelsResult.setDeviceChannelsVoList(new ArrayList<>());
            log.error("getDeviceChannels-deviceSerial"+deviceSerial+"获取萤石云通道信息,getDeviceChannels err:"+e.getMessage());
            throw new Exception();
        }
    }

    /**
     * 根据通道信息 抓拍指定接口的视频图片  云抓拍接口 https://open.ys7.com/api/open/cloud/v1/capture/save
     * 接口名称：云抓拍接口 详情：https://open.ys7.com/help/1387?r=1747620524359.83
     * 接口描述：支持设备抓拍指令采集图片或者抽帧方式采集图片。若使用captureType=1的下发设备抓拍指令方式，请勿频繁调用，每个摄像头调用的间隔需1min以上，否则容易引起设备死机；
     * 若使用captureType=2的抽帧方式，每个摄像头调用的间隔建议在3s以上，抽帧图片会通过消息管道推送。
     * @param deviceSerial
     * @return
     * @throws IOException
     */
    public String getVideoImgChannels(String appKey, String appSecret, String deviceSerial, String channelNo, String projectId, String fileId) throws IOException {
        //获取tocken
        String accessToken = this.getAccessToken(appKey,appSecret);
        //具体参数请参考 萤石云API文档：https://open.ys7.com/help/1414
        FormBody.Builder formBuilder = new FormBody.Builder()
                .add("accessToken", accessToken)
                .add("deviceSerial", deviceSerial)
                .add("channelNo", channelNo) //通道号
                .add("deviceSerial", deviceSerial) //设备序列号
                .add("projectId", projectId) //已创建的项目编号，填写后文件会存储至该项目中
                .add("fileId", fileId) //文件 ID，项目下文件的唯一标识。当captureType=1时需自定义文件 ID；当captureType=2时， 如果没传或传空，程序自动生成，如果传了则使用传入的值
                ;

        Request request = new Request.Builder()
                .url(CAPTURE_SAVE_URL)
                .post(formBuilder.build())
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();

        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            String responseBody = response.body().string();
            log.info("responseBody:" + responseBody);
            Map<String, Object> result = objectMapper.readValue(responseBody, Map.class);
            Map<String, Object> metaMap= (Map<String, Object>) result.get("meta");
            if (metaMap.get("code").equals("200")) {
                return String.valueOf(result.get("data"));
            } else {
                log.warn("result warn:" + result);
                return null;
            }
        } catch (Exception e) {
            throw new IOException("getvideoImgChannels err " + e.getMessage());
        }
    }

    /**
     * 根据通道信息 抓拍指定接口的视频图片  云抓拍接口 https://open.ys7.com/api/open/cloud/v1/capture/save
     * 接口名称：云抓拍接口 详情：https://open.ys7.com/help/1387?r=1747620524359.83
     * 接口描述：支持设备抓拍指令采集图片或者抽帧方式采集图片。若使用captureType=1的下发设备抓拍指令方式，请勿频繁调用，每个摄像头调用的间隔需1min以上，否则容易引起设备死机；
     * 若使用captureType=2的抽帧方式，每个摄像头调用的间隔建议在3s以上，抽帧图片会通过消息管道推送。
     * @param deviceSerial
     * @return
     * @throws IOException
     */
    public String getVideoImgTkChannels(String accessToken, String deviceSerial, String channelNo, String projectId, String fileId) throws IOException {
        //具体参数请参考 萤石云API文档：https://open.ys7.com/help/1414
        FormBody.Builder formBuilder = new FormBody.Builder()
                .add("accessToken", accessToken)
                .add("deviceSerial", deviceSerial)
                .add("channelNo", channelNo) //通道号
                .add("deviceSerial", deviceSerial) //设备序列号
                .add("projectId", projectId) //已创建的项目编号，填写后文件会存储至该项目中
                .add("fileId", fileId) //文件 ID，项目下文件的唯一标识。当captureType=1时需自定义文件 ID；当captureType=2时， 如果没传或传空，程序自动生成，如果传了则使用传入的值
                ;

        Request request = new Request.Builder()
                .url(CAPTURE_SAVE_URL)
                .post(formBuilder.build())
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();

        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            String responseBody = response.body().string();
            log.info("responseBody:" + responseBody);
            Map<String, Object> result = objectMapper.readValue(responseBody, Map.class);
            Map<String, Object> metaMap= (Map<String, Object>) result.get("meta");
            if (metaMap.get("code").equals("200")) {
                return String.valueOf(result.get("data"));
            } else {
                log.warn("result warn:" + result);
                return null;
            }
        } catch (Exception e) {
            throw new IOException("getvideoImgChannels err " + e.getMessage());
        }
    }

    /**************************************** 封装萤石云 接口  ****************************************/
    @Override
    public GetVidoVo getVido(String appKey, String appSecret, Integer channelNo, String deviceSerial) {
        GetVidoVo getVidoVo = new GetVidoVo();
        if (StringUtils.isEmpty(appKey) || StringUtils.isEmpty(appSecret) || channelNo == null || StringUtils.isEmpty(deviceSerial)) {
            log.warn("getVido warn:该设备deviceSerial:"+deviceSerial+"不符合获取视频要求...");
            return getVidoVo;
        }
        try {
            //获取tocken
            String accessToken = this.getAccessToken(appKey, appSecret);
            //获取视频和图片
//            getVidoVo = this.getLiveAddressSnapshot(accessToken, channelNo, deviceSerial);  //获取视频截图 方式1
            getVidoVo =  this.getLiveAddressVideoImg(accessToken, channelNo, deviceSerial,Sysconstant.VIDEO_IMG_PROJECT_ID,Sysconstant.VIDEO_IMG_FILE_ID); //获取视频截图 方式2
        } catch (Exception e) {
            log.error("getVido err:" + e.getMessage());
        }
        return getVidoVo;
    }

    @Override
    public ReDeviceChannelsVoResult getReDeviceChannels(Integer sequenceId, String deviceSerial, String appKey, String appSecret) {
        ReDeviceChannelsVoResult result = new ReDeviceChannelsVoResult();
        List<ReDeviceChannelsVo> reDeviceChannelsVoList = new ArrayList<>();
        result.setSequenceId(sequenceId);
        if (sequenceId == null || StringUtils.isEmpty(deviceSerial) || StringUtils.isEmpty(appKey) || StringUtils.isEmpty(appSecret)) {
            log.warn("getDeviceChannels warn: 入参不符合规范！");
            result.setReDeviceChannelsVoList(reDeviceChannelsVoList);
            return result;
        }
        GetDeviceChannelsResult getDeviceChannelsResults = new GetDeviceChannelsResult();
        try {
            getDeviceChannelsResults = this.getDeviceChannels(deviceSerial, appKey, appSecret);
            if (CollectionUtil.isEmpty(getDeviceChannelsResults.getDeviceChannelsVoList())) {
                log.warn("getDeviceChannels warn: 查询通道列表为空！查询通道列表为空,deviceSerial:"+deviceSerial);
                result.setGetErrBool(getDeviceChannelsResults.isGetErrBool());
                result.setReDeviceChannelsVoList(reDeviceChannelsVoList);
                return result;
            }
            for (DeviceChannelsVo deviceChannelsVo : getDeviceChannelsResults.getDeviceChannelsVoList()) {
                ReDeviceChannelsVo reDeviceChannelsVo = new ReDeviceChannelsVo();
                BeanUtils.copyProperties(deviceChannelsVo, reDeviceChannelsVo);
                reDeviceChannelsVo.setSequenceId(sequenceId);
                reDeviceChannelsVoList.add(reDeviceChannelsVo);
            }
            result.setGetErrBool(getDeviceChannelsResults.isGetErrBool());
            result.setReDeviceChannelsVoList(reDeviceChannelsVoList);
        } catch (Exception e) {
            log.error("getReDeviceChannels err:"+e.getMessage());
            result.setGetErrBool(true);
            result.setReDeviceChannelsVoList(new ArrayList<>());
            return result;
        }
        return result;
    }
}




